#!/bin/bash -e
#   * compile instructions: put this file in
#   *         `steamapps/common/Dyson Sphere Program/CustomMod`
#   * folder, open a terminal in the same folder, and execute:
#   *
#   * ```
#   *     chmod +x powerFull.cs
#   *     ./powerFull.cs
#   * ```
#   *
#   * then the mod will be compiled automatically.
#   *
#   * Here we wrote a shebang like file, which is correct
#   * in my computer (Manjaro XFCE), if such script do not work
#   * in your computer, you could just try the instructions below :

if [ -z "$__DOTNET_CSC" ]; then
    export __DOTNET_CSC="`find /usr/share/dotnet -type f -name dotnet` `find /usr/share/dotnet -name csc.dll`"
    echo '$'"__DOTNET_CSC not set yet, you should execute"
    echo "export __DOTNET_CSC='$__DOTNET_CSC'"
    echo "manually, or this alert will occur each time you execute this script."
fi

__MODE_VERBOSE=80 # is the line number of "#define VERBOSE", may be modified
__MODE_DEBUG__=$((__MODE_VERBOSE+1))
__MODE_RELEASE=$((__MODE_DEBUG__+1))

case $1 in
    V)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    v)       _MODE__SELECT_=$__MODE_VERBOSE     ;;
    VERBOSE) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    verbose) _MODE__SELECT_=$__MODE_VERBOSE     ;;
    D)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    d)       _MODE__SELECT_=$__MODE_DEBUG__     ;;
    DEBUG)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    debug)   _MODE__SELECT_=$__MODE_DEBUG__     ;;
    *)       _MODE__SELECT_=$__MODE_RELEASE     ;;
esac

export GAME_NAME="Software Inc"
export FILE_NAME="$0"
export ASSEMBLY="Assembly-CSharp"
export GAME_BASE_DIR="common/$GAME_NAME"
export PLUGIN_ID="Neutron3529.Cheat"
export NAMESPACE_ID="Neutron3529.Cheat"
# echo $(for i in "${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/$ASSEMBLY"*.dll ; do echo -r:\"$i\" ; done)
( yes "" | head -n $_MODE__SELECT_ | head -n-1  ; tail $FILE_NAME -n+$_MODE__SELECT_ ) | sed s/%%NAMESPACE_ID%%/${NAMESPACE_ID}/g | sed s/%%PLUGIN_ID%%/${PLUGIN_ID}/g | $__DOTNET_CSC -nologo -t:library \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/0Harmony.dll" \
  -r:"${GAME_BASE_DIR}/BepInEx/core/BepInEx.Harmony.dll" \
  `[ -e "${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/netstandard.dll" ] && echo "-r:\"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/netstandard.dll\""` \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/System.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/System.Core.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/UnityEngine.CoreModule.dll" \
  -r:"${GAME_BASE_DIR}/${GAME_NAME}_Data/Managed/mscorlib.dll" \
  -r:"common/Software Inc/Software Inc_Data/Managed/Assembly-CSharp.dll" \
  -r:"common/Software Inc/Software Inc_Data/Managed/Assembly-CSharp-firstpass.dll" \
  -out:"${GAME_BASE_DIR}/BepInEx/plugins/${FILE_NAME%.*}".dll \
  -optimize -deterministic `[ "$_MODE__SELECT_" == "$__MODE_DEBUG__" ] && echo -debug` \
  - && rm -f "${GAME_BASE_DIR}/BepInEx/config/${PLUGIN_ID}.cfg";

if [ -n "$2" ]; then
    git add ${FILE_NAME}
    case $2 in
        R) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        r) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        RANDOM) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        random) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        U) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        u) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        UPLOAD) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        upload) git commit -am "`curl -s http://whatthecommit.com/index.txt`" ;;
        *) git commit -am "$2" ;;
    esac
    git push
fi
exit

#define VERBOSE // the line of __MODE_VERBOSE
#define DEBUG



using System;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;

namespace Cheat
{
    [BepInPlugin("Neutron3529.softwareInc", "softwareInc", "0.1.0")]
    public class Cheat : BaseUnityPlugin {
#if DEBUG
        public static Action<string> logger;
#else
        public static void logger(string s){}
#endif
        public static float non_digital_factor=-1;
        void Start() {
            var harmony=new Harmony("Neutron3529.softwareInc");
#if DEBUG
            logger=Logger.LogInfo;
#endif
            if (Config.Bind<bool>("config", "powerful computer", false, "超级电脑增加工作效率").Value){
                harmony.PatchAll(typeof(FurnitureComputerPowerGetterPatch));
                harmony.PatchAll(typeof(FurnitureGetCostPatch));
                logger("softwareInc-超级大脑增加工作效率-注入完成");
            }
            if (Config.Bind<bool>("config", "powerful actor", true, "超级员工").Value){
                harmony.PatchAll(typeof(ActorGetStateInfluencePatch));
                harmony.PatchAll(typeof(ActorGetPCAddonBonusPatch));
                harmony.PatchAll(typeof(FurnitureGetMaxEffectivenessValuePatch));
                logger("softwareInc-超级员工-注入完成");
            }
            if (Config.Bind<bool>("config", "max bugfix count", true, "最大化bug修复数量").Value){
                harmony.PatchAll(typeof(SoftwareAlphaMaxBugFixPatch));
                logger("softwareInc-最大化bug修复数量-注入完成");
            }
            if (Config.Bind<bool>("config", "add spec exp and remove cap", true, "增加spec经验且取消SpecPoints的限制，同时培训不需要时间").Value){
                harmony.PatchAll(typeof(EmployeeAddSpecExperiencePatch));
                harmony.PatchAll(typeof(GameSettingsGetMaxSpecPointsPatch));
                //harmony.PatchAll(typeof(GameDataGetMaxSpecPointsPatch));
                harmony.PatchAll(typeof(EducationWindowSendEmployeePatch));
                logger("softwareInc-增加spec经验且取消SpecPoints的限制-注入完成");
            }
            if (Config.Bind<bool>("config", "quality always 1", true, "物品永不损坏").Value){
                harmony.PatchAll(typeof(UpgradableDegradePatch));
                harmony.PatchAll(typeof(UpgradableDegradeMonthsPatch));
                logger("softwareInc-物品永不损坏-注入完成");
            }
            if ((non_digital_factor=Config.Bind<float>("config", "non digital factor", -1f, "实体分销占比(小于0禁用)").Value)>0){
                harmony.PatchAll(typeof(MarketSimulationGetPhysicalVsDigitalPatch));
                logger("softwareInc-实体分销占比-注入完成");
            }
            if (Config.Bind<bool>("config", "who are we", true, "员工可以选择用爱发电自愿996且永不辞职").Value){
                harmony.PatchAll(typeof(EmployeeUpdateMoodPatch));
                harmony.PatchAll(typeof(ActorFatiguePatch));
                //harmony.PatchAll(typeof(EmployeeChangeSalaryPatch));
                logger("softwareInc-员工可以选择用爱发电自愿996且永不辞职-注入完成");
            }
            if (Config.Bind<bool>("config", "far sight", true, "员工灵感恒定为最大值").Value){
                harmony.PatchAll(typeof(EmployeeTakeInspirationPatch));
                logger("softwareInc-员工灵感恒定为最大值-注入完成");
            }
            if (Config.Bind<bool>("config", "best design", true, "恒定生产最具灵感的作品").Value){
                harmony.PatchAll(typeof(EmployeeGetWeightedLeadSpecFactorPatch));
                logger("softwareInc-恒定生产最具灵感的作品-注入完成");
            }
        }
        [HarmonyPatch(typeof(Actor), "GetStateInfluence")]
        class ActorGetStateInfluencePatch {
            public static void Postfix(ref Actor __instance, ref float __result) {
                __result=1f;// 这个变量会影响员工头上冒字符的速度，因此不能太大
            }
        }
        [HarmonyPatch(typeof(Actor), "GetPCAddonBonus")]
        class ActorGetPCAddonBonusPatch {
            public static void Postfix(ref Actor __instance, ref float __result) {
                __result=10000f;
            }
        }
        [HarmonyPatch(typeof(Actor), "Fatigue")]
        class ActorFatiguePatch {
            public static void Postfix(ref Actor __instance) {
                __instance.employee.Demanded=-__instance.employee.Worth(-1,false)-10000f;
                __instance.employee.Salary=0f;
                __instance.employee.AskedFor=0f;
                foreach(Employee.ThoughtEffect x in (from x in __instance.employee.Thoughts.List where x.Mood.Negative select x)){
                    __instance.employee.Thoughts.Remove(x.Mood.Thought);
                }
            }
        }
        [HarmonyPatch(typeof(Furniture), "GetMaxEffectivenessValue")]
        class FurnitureGetMaxEffectivenessValuePatch { // 似乎无效？
            public static bool Prefix(ref float __result) {
                __result=10000f;
                return false;
            }
        }
        [HarmonyPatch(typeof(Furniture), "ComputerPower", MethodType.Getter)]
        class FurnitureComputerPowerGetterPatch { // 会更改电脑售价，因此不单独使用
            public static bool Prefix(ref float __result) {
                __result=10000f;
                return false;
            }
        }
        [HarmonyPatch(typeof(Furniture), "GetCost", new Type[] { typeof(string), typeof(float), typeof(int), typeof(float), typeof(bool)} )]
        class FurnitureGetCostPatch { // 跟上面那一条一起使用
            public static bool Prefix(ref float __result) {
                __result=0f;
                return false;
            }
        }
        [HarmonyPatch(typeof(SoftwareAlpha), "MaxBugFix")]
        class SoftwareAlphaMaxBugFixPatch {
            public static bool Prefix(ref float __result, SoftwareAlpha __instance) {
                __result=__instance.Bugs;
                return false;
            }
        }
        [HarmonyPatch(typeof(GameSettings), "GetMaxSpecPoints")]
        class GameSettingsGetMaxSpecPointsPatch {
            public static bool Prefix(ref int __result, Employee.EmployeeRole role) {
                switch (role) {
                case Employee.EmployeeRole.Lead:
                    __result=Employee.LeadSpecs.Length * 3;
                    return false;
                case Employee.EmployeeRole.Programmer:
                    __result=GameSettings.Instance.CodeSpecializations.Length * 3;
                    return false;
                case Employee.EmployeeRole.Designer:
                    __result=GameSettings.Instance.Specializations.Length * 3;
                    return false;
                case Employee.EmployeeRole.Artist:
                    __result=GameSettings.Instance.ArtSpecializations.Length * 3;
                    return false;
                case Employee.EmployeeRole.Service:
                    __result=Employee.ServiceSpecs.Length * 3;
                    return false;
                default:
                    return true;
                }
            }
        }
        [HarmonyPatch(typeof(Employee), "AddSpecExperience")]
        class EmployeeAddSpecExperiencePatch {
            public static bool Prefix(ref float value) {
                value=1f;
                return true;
            }
        }
        [HarmonyPatch(typeof(Employee), "ChangeSalary")]
        class EmployeeChangeSalaryPatch {
            public static bool Prefix(ref Employee __instance, ref float newSalary,ref float askedFor) {
                __instance.Salary=0f;
                __instance.AskedFor=0f;
                __instance.Demanded=0f;
                newSalary=0f;
                askedFor=0f;
                return true;
            }
        }
        [HarmonyPatch(typeof(EducationWindow), "SendEmployee")]
        class EducationWindowSendEmployeePatch {
            public static bool Prefix(ref Actor emp,Employee.EmployeeRole role, string spec) {
                emp.Courses.Add(new KeyValuePair<Employee.EmployeeRole, string>(role, spec));
                emp.LastCourse = SDateTime.Now();
                return false;
            }
        }
        [HarmonyPatch(typeof(MarketSimulation), "GetPhysicalVsDigital")]
        class MarketSimulationGetPhysicalVsDigitalPatch {
            public static bool Prefix(ref float __result) {
                __result=non_digital_factor;
                return false;
            }
        }
        [HarmonyPatch(typeof(Upgradable), "Degrade")]
        class UpgradableDegradePatch {
            public static bool Prefix(ref Upgradable __instance) {
                __instance.Quality=1f;
                return false;
            }
        }
        [HarmonyPatch(typeof(Upgradable), "DegradeMonths")]
        class UpgradableDegradeMonthsPatch {
            public static bool Prefix(ref Upgradable __instance) {
                __instance.Quality=1f;
                return false;
            }
        }
        [HarmonyPatch(typeof(Employee), "UpdateMood")]
        class EmployeeUpdateMoodPatch {
            public static void Postfix(ref Employee __instance) {
                __instance.Hunger = 1f;
                __instance.Energy = 1f;
                __instance.Bladder = 1f;
                __instance.Social = 1f;
                __instance.Stress = 1f;
                __instance.Posture = 1f;
                __instance.JobSatisfaction=2f;
                foreach(Employee.ThoughtEffect x in (from x in __instance.Thoughts.List where x.Mood.Negative select x)){
                    __instance.Thoughts.Remove(x.Mood.Thought);
                }
            }
        }
        [HarmonyPatch(typeof(Employee), "TakeInspiration")]
        class EmployeeTakeInspirationPatch {
            public static void Postfix(ref Employee __instance) {
                __instance.Inspiration=2f;
            }
        }
        [HarmonyPatch(typeof(Employee), "GetWeightedLeadSpecFactor")]
        class EmployeeGetWeightedLeadSpecFactorPatch {
            public static float Postfix(float result) {
                return 100f;
            }
        }
    }
}

